package com.dkd.applet.service.impl;

import cn.elegent.ac.ElegentAC;
import cn.elegent.pay.ElegentPay;
import cn.elegent.pay.constant.Platform;
import cn.elegent.pay.dto.QueryResponse;
import cn.elegent.pay.dto.RefundRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dkd.applet.common.constant.TaskTypeConstant;
import com.dkd.applet.common.constant.VmSystemConstant;
import com.dkd.applet.common.core.ResponseResult;
import com.dkd.applet.common.exception.LogicException;
import com.dkd.applet.config.TopicConfig;
import com.dkd.applet.domain.*;
import com.dkd.applet.domain.dto.PayDto;
import com.dkd.applet.domain.vo.SkuVo;
import com.dkd.applet.mapper.OrderMapper;
import com.dkd.applet.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class OrderServiceImpl  extends ServiceImpl<OrderMapper, Order> implements OrderService  {

    @Autowired
    private VendingMachineService vendingMachineService;
    @Autowired
    private ChannelService channelService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private PolicyService policyService;
    @Autowired
    private PartnerService partnerService;
    @Autowired
    private NodeService nodeService;
    @Autowired
    private ElegentPay elegentPay;
    @Autowired
    private ElegentAC elegentAC;
    /**
     * 创建订单
     *
     * @param payDto
     * @param platform
     * @return
     */
    @Override
    public Order createOrder(PayDto payDto, String platform) {
        //查询货道
        Channel channel = channelService.getChannelsByInnerCode(payDto.getInnerCode(), payDto.getSkuId());
        if(channel== null){
            throw new LogicException("该货道已售罄");
        }
        //查询设备
        VendingMachine vm = vendingMachineService.getVendingMachineByInnerCode(payDto.getInnerCode());
        if(vm==null){
            throw new LogicException("设备不存在");
        }
        //查询商品
        Sku sku = skuService.getById(channel.getSkuId());
        if(sku==null){
            throw new LogicException("商品不存在");
        }
        //根据设备的策略id查询策略表的策略信息
        Policy policy = policyService.getById(vm.getPolicyId());
        if(policy==null){
            throw new LogicException("该设备未设置策略");
        }
        //策略折扣
        BigDecimal discount = new BigDecimal(policy.getDiscount());
        //原价
        BigDecimal price = new BigDecimal(sku.getPrice());
        //计算商品的售价(策略) 优惠后价格四舍五入不保留小数点后位数
        int realPrice = price.multiply(discount).divide(new BigDecimal(100),0, RoundingMode.HALF_UP).intValue();
        //计算合作商账单金额
        Partner partner = partnerService.getById(vm.getPartnerId());
        //如果订单金额低于10分钱则不进行分账
        int bill=0;
        if(realPrice>=10){
            //合作商分账金额=（商品价格*合作商比例）/100
            bill=new BigDecimal(realPrice).multiply(new BigDecimal(partner.getProfitRatio())).divide(new BigDecimal(100),0,RoundingMode.HALF_UP).intValue();
        }
        //查询点位名称
        Node node = nodeService.getById(vm.getNodeId());
        //封装订单对象
        Order order = Order.builder()
                //基本信息
                .orderNo(payDto.getInnerCode()+System.currentTimeMillis()) //订单编号
                .innerCode(vm.getInnerCode()) //设备编号
                .channelCode(channel.getChannelCode()) //货道编号
                .skuId(channel.getSkuId()) //商品编号
                .skuName(sku.getSkuName()) //商品名称
                .classId(sku.getClassId()) //商品类别
                .payStatus(VmSystemConstant.PAY_STATUS_NOPAY) //支付状态:未支付
                .status(VmSystemConstant.ORDER_STATUS_CREATE) //订单状态:创建
                .openId(payDto.getOpenId()) //用户标识
                .payType(platform) //支付方式
                .nodeId(vm.getNodeId()) //点位id
                .nodeName(node.getNodeName()) //点位名称
                .regionId(vm.getRegionId()) //区域id
                .partnerId(vm.getPartnerId()) //合作商id
                .businessType(vm.getBusinessType()) //商圈类型
                .addr(vm.getAddr()) //设备地址
                .price(sku.getPrice()) //商品应付金额
                .createTime(LocalDateTime.now()) //创建日期时间
                .updateTime(LocalDateTime.now()) //修改日期时间
                //计算商品的售价(策略)
                //.amount(realPrice)
                .amount(realPrice) //商品应付金额，测试阶段写死1分
                .bill(bill) //合作商分账金额
                .build();
        //保存并返回订单
        this.save(order);
        return order;
    }

    @Override
    @Scheduled(cron = "0/1 * * * * ?")
    public void checkOrder() {
            //获取当前时间
            Calendar CurrentTime = Calendar.getInstance();
            CurrentTime.add(Calendar.MINUTE, -2);
            //查询超时订单
            LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<Order>();
            wrapper.eq(Order::getStatus, VmSystemConstant.ORDER_STATUS_CREATE)
                    .eq(Order::getPayStatus, VmSystemConstant.PAY_STATUS_NOPAY)
                    .le(Order::getCreateTime, CurrentTime.getTime()); //订单创建时间<=当前时间-2分钟
            List<Order> list = this.list(wrapper);
            //超时订单
            for(Order order : list){

                //取消订单
                Boolean b = elegentPay.closePay(order.getOrderNo(), order.getPayType());
                if(b||order.getPayType().equals(Platform.ALI)){
                    log.info("订单超时取消成功：{}", order.getSkuName());
                    order.setStatus(VmSystemConstant.ORDER_STATUS_INVALID); //订单状态:失效
                    order.setCancelDesc("订单超时未支付");
                    this.updateById(order);
                    elegentAC.publish(TopicConfig.DKD_SERVER_TOPIC, ResponseResult.success("订单超时取消成功：{}", order.getSkuName()));
                    elegentAC.publish(TopicConfig.PAY_SERVER_TOPIC, ResponseResult.error("订单超时"));
                }else{
                    log.info("订单超时取消失败：{}", order.getSkuName());
                    elegentAC.publish(TopicConfig.DKD_SERVER_TOPIC, ResponseResult.success("订单超时取消失败：{}", order.getSkuName()));
                }
            }

            //检查订单中是否有支付状态为退款中的订单
            LambdaQueryWrapper<Order> querywrapper = new LambdaQueryWrapper<Order>();
            querywrapper.eq(Order::getPayStatus, VmSystemConstant.PAY_STATUS_REFUNDING);
            List<Order> list2 = this.list(querywrapper);
            if(CollectionUtils.isEmpty(list2)){
                return;
            }
            for(Order order : list2){
                RefundRequest refundRequest=new RefundRequest();
                refundRequest.setTotalFee(order.getAmount());
                refundRequest.setRefundAmount(order.getAmount());
                refundRequest.setOrderSn(order.getOrderNo());
                refundRequest.setBody(order.getSkuName());
                refundRequest.setRequestNo(System.currentTimeMillis()+"");
                elegentPay.refund(refundRequest,order.getPayType());
            }

    }

    /**
     * 关闭订单
     *
     * @param orderNo
     * @param platform
     * @return
     */
    @Override
    public void closeOrder(String orderNo, String platform) {
        Order order = this.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo));
        if(order==null){
            throw new LogicException("订单不存在！");
        }
        Boolean b = elegentPay.closePay(order.getOrderNo(), order.getPayType());
        if(b||order.getPayType().equals(Platform.ALI)){
            order.setPayStatus(VmSystemConstant.PAY_STATUS_NOPAY);
            order.setStatus(VmSystemConstant.ORDER_STATUS_INVALID);
            order.setCancelDesc("订单被主动取消");
            this.updateById(order);
            log.info("订单取消成功：{}", order.getSkuName());
            elegentAC.publish(TopicConfig.PAY_SERVER_TOPIC, ResponseResult.success("订单取消成功"));
        }else{
            log.info("订单取消失败：{}", order.getSkuName());
        }
    }

    /**
     * 退款
     *
     * @param orderNo  订单编号
     * @param platform 支付方式
     * @return
     */
    @Override
    public boolean refund(String orderNo, String platform) {
        Order order = this.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo));
        if(order==null){
            throw new LogicException("订单不存在！");
        }
        // 判断订单是否已支付
        if(order.getPayStatus().equals(VmSystemConstant.PAY_STATUS_PAYED)
                ||order.getPayStatus().equals(VmSystemConstant.PAY_STATUS_REFUNDING)){
            RefundRequest refundRequest=new RefundRequest();
            refundRequest.setTotalFee(order.getAmount());
            refundRequest.setRefundAmount(order.getAmount());
            refundRequest.setOrderSn(order.getOrderNo());
            refundRequest.setRequestNo(System.currentTimeMillis()+"");
            return elegentPay.refund(refundRequest, platform);
        }else{
            throw new LogicException("订单状态异常，不能退款");
        }
    }
}
